﻿#include "WidgetPropertyEditEntry.h"
#include "ObjectPropertyEditEntryFactory.h"

#include "IntegerEditEntry.h"
#include "BooleanEditEntry.h"
#include "RectEditEntry.h"
#include "SizeEditEntry.h"
#include "EnumEditEntry.h"
#include "FlagsEditEntry.h"
#include "SizePolicyEditEntry.h"
#include "PaletteEditEntry.h"
#include "FontEditEntry.h"
#include "CursorEditEntry.h"
#include "UiTextEditEntry.h"
#include "IconEditEntry.h"
#include "DoubleEditEntry.h"
#include "LocaleEditEntry.h"

#include <QMetaEnum>
#include <QPointer>

REGISTER_PROPERTY_EDIT_ENTRY(Widget)

struct WidgetPropertyEditEntry::WidgetPropertyEditBoxPrivate {
    QPointer<QWidget> object;

    QPointer<BooleanEditEntry> entryEnabled;
    QPointer<RectEditEntry> entryGeometry;
    QPointer<SizePolicyEditEntry> entrySizePolicy;
    QPointer<SizeEditEntry> entryMinSize;
    QPointer<SizeEditEntry> entryMaxSize;
    QPointer<SizeEditEntry> entrySizeIncrement;
    QPointer<SizeEditEntry> entryBaseSize;
    QPointer<PaletteEditEntry> entryPalette;
    QPointer<FontEditEntry> entryFont;
    QPointer<CursorEditEntry> entryCursor;
    QPointer<BooleanEditEntry> entryMouseTracking;
    QPointer<BooleanEditEntry> entryTabletTracking;
    QPointer<EnumEditEntry> entryFocusPolicy;
    QPointer<EnumEditEntry> entryContextMenuPolicy;
    QPointer<BooleanEditEntry> entryAcceptDrops;
    QPointer<UiTextEditEntry> entryWindowTitle;
    QPointer<IconEditEntry> entryWindowIcon;
    QPointer<DoubleEditEntry> entryWindowOpacity;
    QPointer<UiTextEditEntry> entryToolTip;
    QPointer<IntegerEditEntry> entryToolTipDuration;
    QPointer<UiTextEditEntry> entryStatusTip;
    QPointer<UiTextEditEntry> entryWhatsThis;
    QPointer<UiTextEditEntry> entryAccessibleName;
    QPointer<UiTextEditEntry> entryAccessibleDescription;
    QPointer<EnumEditEntry> entryLayoutDirection;
    QPointer<BooleanEditEntry> entryAutoFillBackground;
    QPointer<StringEditEntry> entryStylesheet;
    QPointer<LocaleEditEntry> entryLocale;
    QPointer<UiTextEditEntry> entryWindowFilePath;
    QPointer<EnumEditEntry> entryInputMethosHints;
    QPointer<EnumEditEntry> entryModality;
};

WidgetPropertyEditEntry::~WidgetPropertyEditEntry() { }

WidgetPropertyEditEntry::WidgetPropertyEditEntry(QWidget *parent) : PropertyEditEntry{parent} {
    p.reset(new WidgetPropertyEditBoxPrivate);
    initUi();
    retranslateUi();
}

WidgetPropertyEditEntry::WidgetPropertyEditEntry(void *object, QWidget *parent) : PropertyEditEntry{parent} {
    p.reset(new WidgetPropertyEditBoxPrivate);
    initUi();
    retranslateUi();
    setObject(object);
}

void WidgetPropertyEditEntry::setObject(void *object) {
    p->object = static_cast<QWidget*>(object);
    Q_ASSERT(p->object);
}

void WidgetPropertyEditEntry::onTick() {
    if(!p->object) {
        return ;
    }
    if(!isVisible()) {
        return ;
    }

    const auto &widget = p->object;
    p->entryEnabled->setValue(widget->isEnabled());
    p->entryGeometry->setValue(widget->geometry());
    p->entrySizePolicy->setValue(widget->sizePolicy());
    p->entryMinSize->setValue(widget->minimumSize());
    p->entryMaxSize->setValue(widget->maximumSize());
    p->entrySizeIncrement->setValue(widget->sizeIncrement());
    p->entryBaseSize->setValue(widget->baseSize());
    p->entryPalette->setWidget(widget);
    p->entryPalette->setValue(widget->palette());
    p->entryFont->setValue(widget->font());
    p->entryCursor->setValue(widget->cursor());
    p->entryMouseTracking->setValue(widget->hasMouseTracking());
    p->entryTabletTracking->setValue(widget->hasTabletTracking());
    p->entryFocusPolicy->setValue(widget->focusPolicy());
    p->entryContextMenuPolicy->setValue(widget->contextMenuPolicy());
    p->entryAcceptDrops->setValue(widget->acceptDrops());
    p->entryWindowTitle->setValue(widget->windowTitle());
    p->entryWindowIcon->setValue(widget->windowIcon());
    p->entryWindowOpacity->setValue(widget->windowOpacity());
    p->entryToolTip->setValue(widget->toolTip());
    p->entryToolTipDuration->setValue(widget->toolTipDuration());
    p->entryStatusTip->setValue(widget->statusTip());
    p->entryWhatsThis->setValue(widget->whatsThis());
    p->entryAccessibleName->setValue(widget->accessibleName());
    p->entryAccessibleDescription->setValue(widget->accessibleDescription());
    p->entryLayoutDirection->setValue(widget->layoutDirection());
    p->entryAutoFillBackground->setValue(widget->autoFillBackground());
    p->entryStylesheet->setValue(widget->styleSheet());
    p->entryLocale->setValue(widget->locale());
    p->entryWindowFilePath->setValue(widget->windowFilePath());
    p->entryInputMethosHints->setValue(widget->inputMethodHints());
    p->entryModality->setValue(p->object->windowModality());
}

void WidgetPropertyEditEntry::initUi() {
    setTitle("QWidget");

    // enabled
    p->entryEnabled = new BooleanEditEntry;
    appendChildEntry(p->entryEnabled);
    connect(p->entryEnabled, &BooleanEditEntry::valueChanged, [=](bool value) {
        p->object->setEnabled(value);
    });

    // geometry
    p->entryGeometry = new RectEditEntry;
    appendChildEntry(p->entryGeometry);
    connect(p->entryGeometry, &RectEditEntry::valueChanged, [=](const QRect &value) {
        p->object->setGeometry(value);
    });

    // sizePolicy
    p->entrySizePolicy = new SizePolicyEditEntry;
    appendChildEntry(p->entrySizePolicy);
    connect(p->entrySizePolicy, &SizePolicyEditEntry::valueChanged, [=](const QSizePolicy &value) {
        p->object->setSizePolicy(value);
    });

    // minSize
    p->entryMinSize = new SizeEditEntry;
    appendChildEntry(p->entryMinSize);
    connect(p->entryMinSize, &SizeEditEntry::valueChanged, [=](const QSize &value) {
        p->object->setMinimumSize(value);
    });

    // maxSize
    p->entryMaxSize = new SizeEditEntry;
    appendChildEntry(p->entryMaxSize);
    connect(p->entryMaxSize, &SizeEditEntry::valueChanged, [=](const QSize &value) {
        p->object->setMaximumSize(value);
    });

    // sizeIncrement
    p->entrySizeIncrement = new SizeEditEntry;
    appendChildEntry(p->entrySizeIncrement);
    connect(p->entrySizeIncrement, &SizeEditEntry::valueChanged, [=](const QSize &value) {
        p->object->setSizeIncrement(value);
    });

    // base size
    p->entryBaseSize = new SizeEditEntry;
    appendChildEntry(p->entryBaseSize);
    connect(p->entryBaseSize, &SizeEditEntry::valueChanged, [=](const QSize &value) {
        p->object->setBaseSize(value);
    });

    // palette
    p->entryPalette = new PaletteEditEntry;
    appendChildEntry(p->entryPalette);
    connect(p->entryPalette, &PaletteEditEntry::valueChanged, [=](const QPalette &value) {
        p->object->setPalette(value);
    });

    // font
    p->entryFont = new FontEditEntry;
    appendChildEntry(p->entryFont);
    connect(p->entryFont, &FontEditEntry::valueChanged, [=](const QFont &value) {
        p->object->setFont(value);
    });

    // cursor
    p->entryCursor = new CursorEditEntry;
    appendChildEntry(p->entryCursor);
    connect(p->entryCursor, &CursorEditEntry::valueChanged, [=](const QCursor &value) {
        p->object->setCursor(value);
    });

    // mouseTracking
    p->entryMouseTracking = new BooleanEditEntry;
    appendChildEntry(p->entryMouseTracking);
    connect(p->entryMouseTracking, &BooleanEditEntry::valueChanged, [=](bool value) {
        p->object->setMouseTracking(value);
    });

    // tabletTracking
    p->entryTabletTracking = new BooleanEditEntry;
    appendChildEntry(p->entryTabletTracking);
    connect(p->entryTabletTracking, &BooleanEditEntry::valueChanged, [=](bool value) {
        p->object->setTabletTracking(value);
    });

    // focusPolicy
    p->entryFocusPolicy = new EnumEditEntry;
    p->entryFocusPolicy->setMetaEnum(QMetaEnum::fromType<Qt::FocusPolicy>());
    appendChildEntry(p->entryFocusPolicy);
    connect(p->entryFocusPolicy, &EnumEditEntry::valueChanged, [=](int value) {
        p->object->setFocusPolicy(Qt::FocusPolicy(value));
    });

    // contextMenuPolicy
    p->entryContextMenuPolicy = new EnumEditEntry;
    p->entryContextMenuPolicy->setMetaEnum(QMetaEnum::fromType<Qt::ContextMenuPolicy>());
    appendChildEntry(p->entryContextMenuPolicy);
    connect(p->entryContextMenuPolicy, &EnumEditEntry::valueChanged, [=](int value) {
        p->object->setContextMenuPolicy(Qt::ContextMenuPolicy(value));
    });

    // acceptDrops
    p->entryAcceptDrops = new BooleanEditEntry;
    appendChildEntry(p->entryAcceptDrops);
    connect(p->entryAcceptDrops, &BooleanEditEntry::valueChanged, [=](bool value) {
        p->object->setAcceptDrops(value);
    });

    // windowTitle
    p->entryWindowTitle = new UiTextEditEntry;
    appendChildEntry(p->entryWindowTitle);
    connect(p->entryWindowTitle, &UiTextEditEntry::valueChanged, [=](const QString& text) {
        p->object->setWindowTitle(text);
    });

    // windowIcon
    p->entryWindowIcon = new IconEditEntry;
    appendChildEntry(p->entryWindowIcon);
    connect(p->entryWindowIcon, &IconEditEntry::valueChanged, [=](const QIcon &value) {
        p->object->setWindowIcon(value);
    });

    // windowOpacity
    p->entryWindowOpacity = new DoubleEditEntry;
    appendChildEntry(p->entryWindowOpacity);
    connect(p->entryWindowOpacity, &DoubleEditEntry::valueChanged, [=](double value) {
        p->object->setWindowOpacity(value);
    });

    // toolTip
    p->entryToolTip = new UiTextEditEntry;
    appendChildEntry(p->entryToolTip);
    connect(p->entryToolTip, &UiTextEditEntry::valueChanged, [=](const QString& text) {
        p->object->setToolTip(text);
    });

    // toolTipDuration
    p->entryToolTipDuration = new IntegerEditEntry;
    appendChildEntry(p->entryToolTipDuration);
    connect(p->entryToolTipDuration, &IntegerEditEntry::valueChanged, [=](int value) {
        p->object->setToolTipDuration(value);
    });

    // statusTip
    p->entryStatusTip = new UiTextEditEntry;
    appendChildEntry(p->entryStatusTip);
    connect(p->entryStatusTip, &UiTextEditEntry::valueChanged, [=](const QString& text) {
        p->object->setStatusTip(text);
    });

    // whatsThis
    p->entryWhatsThis = new UiTextEditEntry;
    appendChildEntry(p->entryWhatsThis);
    connect(p->entryWhatsThis, &UiTextEditEntry::valueChanged, [=](const QString& text) {
        p->object->setWhatsThis(text);
    });

    // accessibleName
    p->entryAccessibleName = new UiTextEditEntry;
    appendChildEntry(p->entryAccessibleName);
    connect(p->entryAccessibleName, &UiTextEditEntry::valueChanged, [=](const QString& text) {
        p->object->setAccessibleName(text);
    });

    // accessibleDiscription
    p->entryAccessibleDescription = new UiTextEditEntry;
    appendChildEntry(p->entryAccessibleDescription);
    connect(p->entryAccessibleDescription, &UiTextEditEntry::valueChanged, [=](const QString& text) {
        p->object->setAccessibleDescription(text);
    });

    // layoutDirection
    p->entryLayoutDirection = new EnumEditEntry;
    p->entryLayoutDirection->setMetaEnum(QMetaEnum::fromType<Qt::LayoutDirection>());
    appendChildEntry(p->entryLayoutDirection);
    connect(p->entryLayoutDirection, &EnumEditEntry::valueChanged, [=](int value) {
        p->object->setLayoutDirection(Qt::LayoutDirection(value));
    });

    // autoFillBackground
    p->entryAutoFillBackground = new BooleanEditEntry;
    appendChildEntry(p->entryAutoFillBackground);
    connect(p->entryAutoFillBackground, &BooleanEditEntry::valueChanged, [=](bool value) {
        p->object->setAutoFillBackground(value);
    });

    // stylesheet
    p->entryStylesheet = new StringEditEntry;
    appendChildEntry(p->entryStylesheet);
    connect(p->entryStylesheet, &StringEditEntry::valueChanged, [=](const QString& text) {
        p->object->setStyleSheet(text);
    });

    // locale
    p->entryLocale = new LocaleEditEntry;
    appendChildEntry(p->entryLocale);
    connect(p->entryLocale, &LocaleEditEntry::valueChanged, [=](const QLocale& value) {
        p->object->setLocale(value);
    });

    // windowFilePath
    p->entryWindowFilePath = new UiTextEditEntry;
    appendChildEntry(p->entryWindowFilePath);
    connect(p->entryWindowFilePath, &UiTextEditEntry::valueChanged, [=](const QString& value) {
        p->object->setWindowFilePath(value);
    });

    // inputMethodHints
    p->entryInputMethosHints = new EnumEditEntry;
    p->entryInputMethosHints->setMetaEnum(QMetaEnum::fromType<Qt::InputMethodHint>());
    appendChildEntry(p->entryInputMethosHints);
    connect(p->entryInputMethosHints, &EnumEditEntry::valueChanged, [=](int value) {
        p->object->setInputMethodHints(Qt::InputMethodHints(value));
    });

    // window modality
    p->entryModality = new EnumEditEntry;
    p->entryModality->setMetaEnum(QMetaEnum::fromType<Qt::WindowModality>());
    appendChildEntry(p->entryModality);
    connect(p->entryModality, &EnumEditEntry::valueChanged, [=](int value) {
        p->object->setWindowModality(Qt::WindowModality(value));
    });
}

void WidgetPropertyEditEntry::retranslateUi() {
    p->entryEnabled->setTitle(tr("enabled"));
    p->entryGeometry->setTitle(tr("geometry"));
    p->entrySizePolicy->setTitle(tr("sizePolicy"));
    p->entryMinSize->setTitle(tr("minimumSize"));
    p->entryMaxSize->setTitle(tr("maximumSize"));
    p->entrySizeIncrement->setTitle(tr("sizeIncrement"));
    p->entryBaseSize->setTitle(tr("baseSize"));
    p->entryPalette->setTitle(tr("palette"));
    p->entryFont->setTitle(tr("font"));
    p->entryCursor->setTitle(tr("cursor"));
    p->entryMouseTracking->setTitle(tr("mouseTracking"));
    p->entryTabletTracking->setTitle(tr("tabletTracking"));
    p->entryFocusPolicy->setTitle(tr("focusPolicy"));
    p->entryContextMenuPolicy->setTitle(tr("contextMenuPolicy"));
    p->entryAcceptDrops->setTitle(tr("acceptDrops"));
    p->entryWindowTitle->setTitle(tr("windowTitle"));
    p->entryWindowIcon->setTitle(tr("windowIcon"));
    p->entryWindowOpacity->setTitle(tr("windowOpacity"));
    p->entryToolTip->setTitle(tr("toolTip"));
    p->entryToolTipDuration->setTitle(tr("toolTipDuration"));
    p->entryStatusTip->setTitle(tr("statusTip"));
    p->entryWhatsThis->setTitle(tr("whatsThis"));
    p->entryAccessibleName->setTitle(tr("accessibleName"));
    p->entryAccessibleDescription->setTitle(tr("accessibleDescription"));
    p->entryLayoutDirection->setTitle(tr("layoutDirection"));
    p->entryAutoFillBackground->setTitle(tr("autoFillBackground"));
    p->entryStylesheet->setTitle(tr("stylesheet"));
    p->entryLocale->setTitle(tr("locale"));
    p->entryWindowFilePath->setTitle(tr("windowFilePath"));
    p->entryInputMethosHints->setTitle(tr("inputMethodHints"));
    p->entryModality->setTitle(tr("windowModality"));
}
